Représentation approximative des nombres réels
Nombre décimaux
Un nombre décimal est un nombre s'écrivant sous la forme $\dfrac{x}{10^{n}}$, où $x$ est un entier relatif.
$\dfrac{13}{4} = \dfrac{325}{100}=\dfrac{325}{10^2}=3,25 = 3,25_{10}$ est un décimal.
$\dfrac{-5}{2}=-2,5=-2,5_{10}$ est un décimal.
$\dfrac{1}{3}=0.3333333...$ n'est pas un décimal. On ne peut pas écrire ce nombre sous la forme $\dfrac{x}{10^{n}}$.
Nombre dyadiques
Par analogie avec les nombres décimaux, on appelle nombres dyadiques les nombres qui s'écrivent sous la forme $\dfrac{x}{2^{n}}$, avec $x$ entier relatif et $n$ entier.
$\dfrac{13}{4}=\dfrac{13}{2^{2}}$ est un nombre dyadique.
$\dfrac{1}{5}=\dfrac{2}{10}$ est un décimal mais pas un nombre dyadique.
Développement dyadique d'un nombre dyadique
On appelle développement dyadique d'un nombre dyadique l'écriture en binaire de ce nombre.
Ce développement dyadique est l'écriture en base 2 d'un nombre dyadique.
Écriture binaire d'un nombre dyadique
Pour obtenir le développement dyadique d'un nombre dyadique $\dfrac{x}{2^{n}}$, on prend le nombre binaire correspondant à $x$ et on insère une virgule avant le $n$-ième bit en partant de la fin.
Écrivons le développement dyadique de $2,5$.
$2,5$ est un nombre dyadique puisque $2,5=\dfrac{5}{2}=\dfrac{5}{2^1}$. Donc on peut écrire son développement dyadique.
On détermine l'écriture en binaire de $5$ :$5_{10}=101_{2}$.
On insère une virgule avant le n-ième bit en partant de la fin.$2,5_{10}=10,1_{2}$.
Écrire le développement dyadique de $31,25$
Cette méthode est fastidieuse parce qu'elle oblige de passer par l'écriture dyadique. De plus que faire des nombres qui ne sont pas dyadiques ?
Partons tout de suite sur un exemple : comment représenter 5,1875 en binaire ?
Il nous faut déjà représenter 5, ça, pas de problème : 101
Comment représenter le ",1875" ?
On multiplie 0,1875 par 2 : 0,1875 x 2 = 0,375. On obtient 0,375 que l'on écrira $\color{red}{0} + \color{blue}{0,375}$.
On multiplie 0,375 par 2 : 0,375 x 2 = 0,75. On obtient 0,75 que l'on écrira $\color{red}{0} + \color{blue}{0,75}$.
On multiplie 0,75 par 2 : 0,75 x 2 = 1,5. On obtient 1,5 que l'on écrira $\color{red}{1} + \color{blue}{0,5}$ (quand le résultat de la multiplication par 2 est supérieur à 1, on garde uniquement la partie décimale).
On multiplie 0,5 par 2 : 0,5 x 2 = 1,0. On obtient 1,0 que l'on écrira $\color{red}{1} + \color{blue}{0,0}$ (la partie décimale est à 0, on arrête le processus).
On obtient une succession de "$\color{red}{a} + \color{blue}{0,b}$" où $a=0$ ou $a=1$ avec :
"$\color{red}{0} + \color{blue}{0,375}$",
"$\color{red}{0} + \color{blue}{0,75}$",
"$\color{red}{1} + \color{blue}{0,5}$" et
"$\color{red}{1} + \color{blue}{0,0}$".
Il suffit maintenant de "prendre" tous les "$\color{red}{0/1}$" (dans l'ordre de leur obtention) afin d'obtenir la partie décimale de notre nombre : $\color{red}{0011}$
Nous avons $101,0011_{2}$ qui est la représentation binaire de $(5,1875)_{10}$.
Trouvez la représentation binaire de :
$4,125_{10}$.
$7,09375_{10}$.
$13,325_{10}$.
Il est possible de retrouver une représentation décimale en base 10 à partir d'une représentation en binaire.
Partons de $(100,0101)_2$.
Pas de problème pour la partie entière, nous obtenons "4".
Pour la partie décimale nous devons écrire : $0 \times 2^{-1} + 1 \times 2^{-2} + 0 \times 2^{-3} + 1 \times 2^{-4}$ $=\dfrac{1}{2^2}+\dfrac{1}{2^4}$ $=\dfrac{1}{4}+\dfrac{1}{16}$ $=0,25+0,0625$ $= 0,3125$.
Nous avons donc $4,3125_{10}$.
Trouvez la représentation décimale de : $100,001_{2}$.
En base dix, il est possible d'écrire les très grands nombres et les très petits nombres grâce aux "puissances de dix" (exemples 6,02.1023 ou 6,67.10-11).
Il est possible de faire exactement la même chose avec une représentation
binaire, puisque nous sommes en base 2, nous utiliserons des "puissances de deux" à la place des "puissances dix" (exemple 101,01001101.2101, où l'exposant est aussi un nombre écrit en binaire.
Pour passer d'une écriture sans "puissance de deux" à une écriture avec "puissance de deux", il suffit décaler la virgule : 1101,1001 = 1,1011001.211 pour passer de "1101,1001" à "1,1011001" nous avons décalé la virgule de 3 rangs vers la gauche d'où le "211" (attention de ne pas oublier que nous travaillons en base 2 le "11" correspond bien à un décalage de 3 rangs de la virgule, car (11) 2=(3)10).
1,1011001 est appelé la mantisse. C'est toujours un nombre compris entre 1 et 2.
11 est appelé l'exposant.
Si l'on désire décaler la virgule vers la gauche, il va être nécessaire d'utiliser des "puissances de deux négatives" 0,0110 = 1,10.2-10, nous décalons la virgule de 2 rangs vers la droite, d'où le "-10".
Pour compléter ce cours, vous pouvez faire une recherche sur le norme IEEE-754 qui n'est pas au programme.
Cette norme définit le codage sur 64 bits des nombres à virgule flottante sous la forme $s\ m\ 2^{n}$, où les lettres $s$, $m$ et $n$n correspondent aux trois informations :
un signe $s$ : un bit est réservé. Il vaut 0 pour le signe "-" et 1 pour le signe "+".
un exposant "décalé" $e$ codé sur 11 bits qui vaut $n+1023$ afin que $e$ soit toujours un nombre positif même si l'exposant $n$ est négatif.
une mantisse tronquée $m-1$ sur 52 bits avec $m$ compris entre 1 et 2 pour coder les 52 premiers bits de la partie fractionnaire de $m$.
Trouvez la représentation binaire de : (0,1)10.
Que remarquez-vous ?
Il existe des nombres décimaux qui ne sont pas dyadiques. Ils n'acceptent pas de développement dyadique fini. Par conséquent leur représentation machine sera nécessairement tronquée. Cela engendrera des erreurs dans les opérations.
Il existe une anecdote illustrant ce problème:
Il ne faudrait surtout pas croire que ces petites erreurs de calcul et d’arrondi soient négligeables, et l’anecdote suivante devrait vous convaincre de l’importance qu’il y a à en prendre conscience.
Le 25 février 1991, à Dharan en Arabie Saoudite, un
missile Patriot américain a raté l’interception d’un missile Scud irakien, ce dernier provoquant la mort de 28 personnes.
La commission d’enquête chargée de comprendre la raison de cet échec a mis en évidence le défaut suivant : L’horloge
interne du missile Patriot mesure le temps en 1/10s.
Pour obtenir le temps en seconde, le système multiplie ce nombre par 10 en utilisant un registre de 24 bits en virgule fixe. Or 1/10 n’est pas un nombre dyadique donc a été arrondi :
le registre de 24 bits contient `0,00011001100110011001100_2` et induit une erreur binaire de `0,0000000000000000000000011001100..._2`, soit approximativement 0,000000095 en notation décimale.
En multipliant cette quantité par le nombre
de 1/10s pendant 100h (le temps écoulé entre la mise en marche du système et le lancement du missile Patriot), on obtient le décalage entre
l’horloge interne de missile et le temps réel, soit : 0,000000095 × 100 × 3600 × 10 ≈ 0,34s.
Or, un missile Scud vole à la vitesse approximative de 1,676m/s donc parcourt plus de 500m en 0,34s, ce qui le fait largement sortir de la zone d’acquisition de sa cible par le missile d’interception.
Cette anecdote est tirée d'un site intéressant : catastrophes numériques
Quelle valeur prend le booléen 0.1+0.2 == 0.3
.
Est-ce cohérent avec vos connaissances en mathématiques ?
Déterminer la représentation binaire de $(0.1)_{10}$.
Déterminer la représentation binaire de $(0.2)_{10}$.
Expliquer pourquoi en informatique $0.1+0.2\neq 0.3$.
Vérifier la valeur approchée affichée pour $0.1+0.2$.
Outre les erreurs de précision liée à la troncature de l'écriture binaire, il peut apparaître d'autres problèmes liés à la représentation des flottants :
Des additions d'"entiers" fausses si l'écart de valeur est important :
9876543210987652.0+1.0
prend la valeur
9876543210987652.0
au lieu de celle
mathématique attendue 9876543210987653.0
.
Des additions non "commutatives" :
1.0 + 1.0 + 9876543210987652.0
prend bien la valeur
9876543210987654.0
mais 9876543210987652.0 + 1.0 + 1.0
prend celle
erronée et différente 9876543210987652.0
.
Écrire en premier lieu une fonction decbin(n)
qui à un entier n
renvoie sa décomposition en binaire sous forme de liste.
Copier puis compléter le script suivant en vous servant des commentaires et du test proposé ci-dessus.
def decbin(n: int) -> list:
l = []
q = ...
while ...:
l.append(...)
q = ...
l...
return l
Écrire en python une fonction deci_en_bin(n)
qui a un nombre décimal
n
renvoie son écriture binaire sur 24 bits sous la forme d'une liste. La virgule sera une chaine de caractère.
Rappel : int(f)
renvoie la partie entière d'un flottant
f
.
Copier puis compléter le script suivant en vous servant des commentaires et du test proposé ci-dessus.
def deci_en_bin(n: float) -> list:
binaire = decbin(int(n))
binaire.append(',')
espace = len(binaire)
while espace <= ...:
n = ...
binaire.append(int(n))
espace += 1
return binaire
Écrire une fonction bindec(l)
qui a une liste de correspondant à l'écriture en binaire d'un nombre renvoie le nombre codé en décimal.
Copier puis compléter le script suivant en vous servant des commentaires et du test proposé ci-dessus.
def bindec(l: list) -> int:
n = ...
for i in range(...):
n = ... + ... * 2**(...)
return n
Écrire une fonction recherche_de_position(l)
qui a une liste de longueur 24 renvoie la position du caractère ,
ou None
si le caractère n'est pas présent.
Copier puis compléter le script suivant en vous servant des commentaires et du test proposé ci-dessus.
def recherche_position_virgule(l):
position = ...
while position < ... and l[position] != ...:
position = ...
if position == 24:
position = ...
return position
Écrire en python une fonction bin_en_deci(l)
qui a un nombre en binaire l
écrit sur 24 bits sous la forme d'une liste renvoie le décimal en base 10 correspondant.
Copier puis compléter le script suivant en vous servant des commentaires et du test proposé ci-dessus.
def bin_en_deci(l: list) -> float:
position = recherche_position_virgule(l)
n = len(l)
if position == None:
nombre = ... # penser à se servir d'une fonction déjà construite
else:
nombre = bindec(l[0:position]) # liste réduite aux éléments d'indice compris entre 0 et position (position exclu)
i = ...
puissance = ...
while i < ...:
nombre = nombre + ...*2**(...)
i = ...
puissance = ...
return nombre
Écrire le développement dyadique de $\dfrac{201}{16}$, c'est-à-dire de $12,5625$.
Propriétaire des ressources ci-dessous : ministère de l'Éducation nationale et de la jeunesse, licence CC BY SA NC
Voici une sélection de questions issues de la banque nationale de sujets, répondez à ces questions (attention, cette sélection n'est pas exhaustive).
Un seul des réels suivants (écrits en base 10) n'a pas une écriture finie en base 2. Lequel ?
Réponses :
A- 1,25
B- 1,5
C- 1,6
D- 1,75
Les QCM suivants sont issus de https://genumsi.inria.fr.
Que peut-on dire du programme Python suivant de calcul sur les nombres flottants ?
x = 1.0
while x != 0.0:
x = x - 0.1
Réponses :
A- L’exécution peut ne pas s’arrêter, si la variable x n’est jamais égale exactement à 0.0
B- À la fin de l’exécution, la variable x vaut -0.000001
C- À la fin de l’exécution, la variable x vaut 0.000001
D- L’exécution s’arrête sur une erreur FloatingPointError.
Parmi les nombres suivants, écrits en base 10, lequel à une écriture infinie en base 2 :
Réponses :
A- 0,75
B- 1,25
C- 1,7
D- 3,5
L'écriture binaire du nombre décimal 49,78125 est :
Réponses :
A- 110001,11001
B- 110001,01011
C- 110001,01101
D- infinie
L'écriture décimale du nombre binaire 110,1011 est :
Réponses :
A- 6,625
B- 6,6875
C- 6,675
D- 6,6825
L'écriture binaire de 13,25 en virgule fixe est ...
Réponses :
A- 1011,010
B- 1101,001
C- 1101,010
D- 101,001
Quelle est l'écriture décimale du nombre qui s'écrit 101,0101 en binaire ?
Réponses :
A- 5,3125
B- 5,05
C- 5
D- 5,0101
Quel est le développement dyadique (écriture binaire) du nombre décimal 12,6875 ?
Réponses :
A- $(1100,1011)_2$
B- $(1100,1001)_2$
C- $(1100,0011)_2$
D- $(1100,10111)_2$
Les différents
auteurs mettent l'ensemble du site à disposition selon les termes de la licence Creative
Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0
International